package com.mrogrape.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;


/**
 * 包含一组快捷的读取或者写入文本的方法。
 * 
 * <p>
 * 虽然此类中的大部分方法已经优化了性能以实现最优化的读取以及写入速度，但是由于此类所
 * 有的方法在操作完成之前都无法返回，所以并不适宜用来操作大型的文本文件。正确的做法是
 * 使用{@link com.mrogrape.io.TextReader}来读取大型文本并使用
 * {@link com.mrogrape.io.TextWriter}来完成大型文本的保存。而TextIO用来读取或保存类似
 * 配置文件之类的小型文本。
 * 
 * @author  Ice Spring
 * @version 1.0 
 */
public class TextIO {

	/**
	 * 以默认字符集读取文本文件。
	 * 
	 * @param input 需要读取的文本文件
	 * @return 储存着文件中全部文本的字符串构建器。
	 * @throws FileNotFoundException 如果文件未找到
	 * @throws IOException 如果发生IO异常
	 */
	public static StringBuilder readText(File input) 
	throws FileNotFoundException,IOException{
		StringBuilder sb = new StringBuilder();
		BufferedReader br = new BufferedReader(new FileReader(input));

		char[] cbuf = new char[TextIO.BUFFER_SIZE];
		int read = 0;
		while((read = br.read(cbuf))!=-1){
			sb.append(cbuf, 0, read);
		}
		br.close();
		return sb;
	}

	/**
	 * 以指定的字符集读取文本文件。
	 * 
	 * @param input 文本文件。
	 * @param charset 字符集
	 * @return 包含文本文件中全部文本的字符串构建器。
	 * @throws UnsupportedEncodingException 如果编码不被支持。
	 * @throws FileNotFoundException 如果文件未找到
	 * @throws IOException 如果发生IO异常
	 */
	public static StringBuilder readText(File input,String charset) 
	throws UnsupportedEncodingException, FileNotFoundException, IOException{
		StringBuilder sb = new StringBuilder();

		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(input), charset));
		char[] cbuf = new char[TextIO.BUFFER_SIZE];
		int read = -1;
		while((read = br.read(cbuf))!=-1){
			sb.append(cbuf, 0, read);
		}
		br.close();

		return sb;
	}

	/**
	 * 以默认的字符集将全部写入指定文件。如果文件不存在将会被创建，已经存在的文件
	 * 将会被覆盖。
	 * 
	 * @param text 需要写入文件的文本。
	 * @param output 指定的输出文件。
	 * @throws FileNotFoundException 如果文件未找到并无法创建。
	 * @throws IOException 如果发生IO异常。
	 */
	public static void writeText(String text,File output)
	throws FileNotFoundException,IOException{

		StringReader sr = new StringReader(text);
		BufferedWriter bw = new BufferedWriter(new FileWriter(output));

		char[] cbuf = new char[TextIO.BUFFER_SIZE];
		int read = -1;
		while((read = sr.read(cbuf)) != -1){
			bw.write(cbuf, 0, read);
		}

		sr.close();
		bw.close();

	}

	/**
	 * 以默认的字符集将文本写入指定文件，并指定行分隔符。如果文件不存在将会被创建，已
	 * 经存在的文件将会被覆盖。
	 * 
	 * <p>
	 * <b>注意：</b>此方法将替换文本中可识别的行分割符为指定的行分隔符。可识别的行
	 * 分隔符一般是“\n”（UNIX）或者“\r\n”（windows），这将取决于
	 * {@link java.io.BufferedReader}的readline()方法。提示：指定的行分隔符
	 * 也不一定是真正的系统认可的换行符。
	 * 
	 * 
	 * @param text 需要写入的文本。
	 * @param lineSeparator 指定的行分隔符。
	 * @param output 目标输出文件。
	 * @throws FileNotFoundException 如果文件未找到。
	 * @throws IOException 如果发生IO异常。
	 */
	public static void writeText(String text,String lineSeparator,File output)
	throws FileNotFoundException,IOException{
		char[] separator = lineSeparator.toCharArray();
		BufferedReader br = new BufferedReader(new StringReader(text));
		BufferedWriter bw = new BufferedWriter(new FileWriter(output));

		String line = null;
		while((line = br.readLine()) != null){
			bw.write(line.toCharArray());
			bw.write(separator);
		}

		br.close();
		bw.close();

	}

	/**
	 * 以指定的字符集将文本写入指定的文件。如果文件不存在将会被创建，已经存在的文件
	 * 将会被覆盖。
	 * 
	 * 
	 * @param text 需要写入文件的文本。
	 * @param output 输出的文件
	 * @param charset 输出时使用的字符集
	 * @throws UnsupportedEncodingException 如果字符集不被支持
	 * @throws FileNotFoundException 如果文件未找到并无法创建。
	 * @throws IOException 如果发生IO错误。
	 */
	public static void writeText(String text,File output,String charset)
	throws UnsupportedEncodingException, FileNotFoundException, IOException{
		StringReader sr = new StringReader(text);
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
				new FileOutputStream(output),charset));

		char[] cbuf = new char[TextIO.BUFFER_SIZE];
		int read = -1;
		while((read = sr.read(cbuf)) != -1){
			bw.write(cbuf, 0, read);
		}

		sr.close();
		bw.close();
	}

	/**
	 * 以指定的字符集和行分隔符将文本写入指定的文件。如果文件不存在将会被创建，已经存
	 * 在的文件将会被覆盖。
	 * 
	 * <p>
	 * <b>注意：</b>此方法将替换文本中可识别的行分割符为指定的行分隔符。可识别的行
	 * 分隔符一般是“\n”（UNIX）或者“\r\n”（windows），这将取决于
	 * {@link java.io.BufferedReader}的readline()方法。提示：指定的行分隔符
	 * 也不一定是真正的系统认可的换行符。
	 * 
	 * @param text 需要写入文件的文本。
	 * @param output 输出的文件
	 * @param charset 输出时使用的字符集
	 * @throws UnsupportedEncodingException 如果字符集不被支持
	 * @throws FileNotFoundException 如果文件未找到并无法创建。
	 * @throws IOException 如果发生IO错误。
	 */
	public static void writeText(String text,String lineSeparator,File output,String charset)
	throws UnsupportedEncodingException, FileNotFoundException, IOException{
		char[] separator = lineSeparator.toCharArray();
		BufferedReader br = new BufferedReader(new StringReader(text));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
				new FileOutputStream(output),charset));

		String line = null;
		while((line = br.readLine()) != null){
			bw.write(line.toCharArray());
			bw.write(separator);
		}

		br.close();
		bw.close();
	}

	/**
	 * 以默认的字符集将文本写入指定的文件,并使用本地系统的行分隔符。如果文件不存在将
	 * 会被创建，已经存在的文件将会被覆盖。
	 * 
	 * <p>
	 * 行分隔符由系统属性 line.separator 决定。
	 * 
	 * @param text 需要写入的文本。
	 * @param output 需要写入的文件。
	 * @throws FileNotFoundException 文件无法创建。
	 * @throws IOException 如果发生IO错误。
	 */
	public static void writeNativeText(String text,File output)
	throws FileNotFoundException, IOException{
		BufferedReader br = new BufferedReader(new StringReader(text));
		PrintWriter pw = new PrintWriter(new FileWriter(output));
		String line = null;
		while((line = br.readLine()) != null){
			pw.println(line);
		}

		pw.close();
		br.close();
	}

	/**
	 * 以指定的字符集将文本写入指定的文件,并使用本地系统的行分隔符。如果文件不存在将
	 * 会被创建，已经存在的文件将会被覆盖。
	 * 
	 * <p>
	 * 行分隔符由系统属性 line.separator 决定。
	 * 
	 * @param text 需要写入的文本。
	 * @param output 需要写入的文件。
	 * @param charset 使用的字符集。
	 * @throws UnsupportedEncodingException 如果字符集不被支持。
	 * @throws FileNotFoundException 如果文件未找到或无法创建。
	 * @throws IOException 如果发生IO异常。
	 */
	public static void writeNativeText(String text,File output,String charset)
	throws UnsupportedEncodingException, FileNotFoundException, IOException{
		BufferedReader br = new BufferedReader(new StringReader(text));
		PrintWriter pw = new PrintWriter(new OutputStreamWriter(
				new FileOutputStream(output),charset));
		String line = null;
		while((line = br.readLine()) != null){
			pw.println(line);
		}

		pw.close();
		br.close();
	}

	private TextIO(){
		//阻止实例化。
	}

	/**
	 * 读取或写入文件时使用的缓存大小(如果需要)。
	 */
	private static final int BUFFER_SIZE = 1024;



}
